
/*							*/
/*  Indexed Sequential Access Method			*/
/*  Relational Database Systems, Inc.			*/
/*							*/
/*		Proprietary Data			*/
/*    This document contains proprietary information	*/
/* and trade secrets which are the property of		*/
/* Relational Database Systems, Inc. (RDSI). This	*/
/* document is submitted to recipient in confidence.	*/
/* The information contained herein may not be used,	*/
/* copied or disclosed in whole or in part except as	*/
/* permitted by written agreement signed by an officer	*/
/* of RDSI.						*/
/*							*/

/*
 * isam read routines
 *
 * Relational Database Systems, Inc.
 * Roy Harrington	November 4, 1981
 */

#include "isdec.c"

/*
 * position current pointer and read record
 */

isread(isfd, record, mode)

int isfd;
char record[];
register int mode;
{
	register struct keydesc *curkey;
	register struct item *curitem;
	register int lockmode, dir;

	if (isenter(isfd, ISINPUT) == -1) return(-1);

	lockmode = mode & LOCKMASK;		/* locking mode		*/
	switch(lockmode)
	    {
	    case 0:
		if (openp->o_mode & ISAUTOLOCK)
		    lockmode = ISLOCK;
		break;
	    case ISLOCK:
		break;
	    default:
		iserrno = EBADARG;
		return(isexit());
	    }

	curkey  = &openp->o_curkey;
	curitem = &openp->o_curitem;

	mode &= IOMASK;				/* sequence mode	*/
	switch(mode)
	    {
	    case ISFIRST:
	    case ISLAST:
	    case ISEQUAL:
	    case ISGREAT:
	    case ISGTEQ:
		kposition(record, 0, mode);	/* position first	*/
		break;

	    case ISNEXT:
	    case ISPREV:
	    case ISCURR:
		if (curkey->k_nparts == 0)	/* physical order ?	*/
		    {
		    treeflags = treelev = 0;
		    treeitem.it_ptr = curitem->it_ptr;
		    break;
		    }
		if (btcurrent() != 0)		/* setup current tree	*/
		    goto bad;
		break;

	    default:
		iserrno = EBADARG;
	    }

	if (iserrno) return(isexit());		/* any errors so far ?	*/

	if (mode == ISPREV || mode == ISLAST)
	    {					/* process previous	*/
	    dir = ISPREV;
	    btmove(curkey, ISPREV);
	    }
	else dir = ISNEXT;

	if (mode == ISNEXT &&
	    ((openp->o_flags & OCURREAD) || (treeflags & BEGFILE)))
	    {					/* process next		*/
	    btmove(curkey, ISNEXT);
	    }

	if (treeflags & (BEGFILE|ENDFILE))
	    iserrno = EENDFILE;
	else
	    {
	    while (dataread(record, treeitem.it_ptr) != 0)
		{				/* find good record	*/
		if (treeflags) goto bad3;
		btmove(curkey, dir);
		}

	    itcopy(&treeitem, curitem, curkey);	/* new current item	*/
	    if (lockmode && lkrecord(curitem->it_ptr, LOCKCOND))
		goto bad2;
			/* check next key for duplicate - cobol necessity */
	    if (curkey->k_flags & ISDUPS)
		{
		btdups(curkey, dir);		/* check next key for dup */
		}

	    openp->o_flags |= OCURREAD;		/* read current record	*/
	    }

	return(isexit());

bad:	if (!iserrno) iserrno = ENOCURR;
bad2:	if (!iserrno) iserrno = ELOCKED;
bad3:	if (!iserrno) iserrno = EENDFILE;
	return(isexit());
}

/*
 * position current record
 */

isstart(isfd, keydesc, keylen, record, mode)

int isfd;
struct keydesc *keydesc;
int keylen;
char record[];
int mode;
{
	struct keydesc key;
	register struct keydesc *keyp = &key;

	if (isenter(isfd, ISINPUT) == -1) return(-1);

	kycopy(keydesc, keyp);
	if (keyp->k_nparts == 0)		/* physical key ?	*/
	    {
	    keyp->k_flags = 0;
	    keyp->k_len = 0;
	    }
	else if (kysearch(keyp, 0) <= 0)	/* search for key	*/
	    {
	    iserrno = EBADKEY;
	    goto err;
	    }

	kycopy(keyp, &openp->o_curkey);		/* set new current key	*/
	keydesc->k_flags = keyp->k_flags;	/* return k_flags to user */

	kposition(record, keylen, mode);	/* position current	*/

err:
	return(isexit());
}

/*
 * initialize tree position
 */

STATIC int kposition(record, keylen, mode)

char record[];
int keylen;
int mode;
{
	struct item item;
	register struct keydesc *keydesc;

	keydesc = &openp->o_curkey;

	switch(mode)
	    {
	    case ISFIRST:
	    case ISLAST:
		if (keydesc->k_nparts == 0)	/* physical read ?	*/
		    {
		    treeitem.it_ptr =
			(mode == ISFIRST) ? 1L :	/* first record	*/
			ld4(dictp->d_nextdata) + 1L;	/* last record+1*/
		    treeflags = treelev = 0;
		    }
		else btposition(keydesc, mode);
		break;
	    case ISEQUAL:
	    case ISGREAT:
	    case ISGTEQ:
		if (keydesc->k_nparts == 0) goto bad;
		itmake(record, &item, keydesc);
		btsearch(&item, keydesc, keylen, (mode == ISGREAT));
		if (treeflags & (BEGFILE|ENDFILE))
		    iserrno = ENOREC;
		if (mode == ISEQUAL &&
			itcompare(&item, &treeitem, keydesc, keylen) != 0)
		    iserrno = ENOREC;
		break;
	    default:
	    bad:
		iserrno = EBADARG;
		break;
	    }

	openp->o_flags &= ~(OCURPOS|OCURREAD);
	if (iserrno)
	    return;
	itcopy(&treeitem, &openp->o_curitem, keydesc);
					/* set new current item	*/
	openp->o_flags |= OCURPOS;
}
